$ python3 -m pyperf stats outliers.json -q Total duration: 11.6 sec Start date: 2017-03-16 16:30:01 End date: 2017-03-16 16:30:16 Raw value minimum: 135 ms Raw value maximum: 197 ms
Number of calibration run: 1 Number of run with values: 20 Total number of run: 21
Number of warmup per run: 1 Number of value per run: 3 Loop iterations per value: 2^15 Total number of values: 60
Minimum: 4.12 us Median +- MAD: 4.25 us +- 0.05 us Mean +- std dev: 4.34 us +- 0.31 us Maximum: 6.02 us
0th percentile: 4.12 us (-5% of the mean) -- minimum 5th percentile: 4.15 us (-4% of the mean) 25th percentile: 4.21 us (-3% of the mean) -- Q1 50th percentile: 4.25 us (-2% of the mean) -- median 75th percentile: 4.30 us (-1% of the mean) -- Q3 95th percentile: 4.84 us (+12% of the mean) 100th percentile: 6.02 us (+39% of the mean) -- maximum
for loops in range_it: mydict['0'] mydict['100'] mydict['200'] mydict['300'] mydict['400'] mydict['500'] mydict['600'] mydict['700'] mydict['800'] mydict['900']
return pyperf.perf_counter() - t0
runner = pyperf.Runner() mydict = {str(k): k for k inrange(1000)} # inner-loops: dict[str] is duplicated 10 times runner.bench_time_func('dict[str]', bench_dict, mydict, inner_loops=10)
/*[clinic input] _pickle.Pickler.dump obj: 'O' argument document(optional) / Write a pickled representation of the given object to the open file. [clinic start generated code]*/
/* Check whether the Pickler was initialized correctly (issue3664). Developers often forget to call __init__() in their subclasses, which would trigger a segfault without this check. */ if (self->write == NULL) { PyErr_Format(PicklingError, "Pickler.__init__() was not called by %s.__init__()", Py_TYPE(self)->tp_name); returnNULL; }
// 使用PyArg_ParseTuple进行参数解析 if (!PyArg_ParseTuple(args, "O:dump", &obj)) returnNULL;
if (_Pickler_ClearBuffer(self) < 0) returnNULL;
if (dump(self, obj) < 0) returnNULL; if (_Pickler_FlushToFile(self) < 0) returnNULL; Py_RETURN_NONE; }
/*[clinic input] _pickle.Pickler.dump obj: 'O' / Write a pickled representation of the given object to the open file. [clinic start generated code]*/
static PyObject * _pickle_Pickler_dump(PicklerObject *self, PyObject *obj) /*[clinic end generated code: output=87ecad1261e02ac7 input=199cc5a0e7561167]*/ { /* Check whether the Pickler was initialized correctly (issue3664). Developers often forget to call __init__() in their subclasses, which would trigger a segfault without this check. */ if (self->write == NULL) { PickleState *st = _Pickle_GetGlobalState(); PyErr_Format(st->PicklingError, "Pickler.__init__() was not called by %s.__init__()", Py_TYPE(self)->tp_name); returnNULL; }
if (_Pickler_ClearBuffer(self) < 0) returnNULL;
if (dump(self, obj) < 0) returnNULL;
if (_Pickler_FlushToFile(self) < 0) returnNULL;
Py_RETURN_NONE; }
// _pickle.h 头文件对应的宏定义也会自动生成以下代码块 PyDoc_STRVAR(_pickle_Pickler_dump__doc__, "dump($self, obj, /)\n" "--\n" "\n" "Write a pickled representation of the given object to the open file.");
/*[clinic input] _pickle.Pickler.dump obj: object num: 'i' / Write a pickled representation of the given object to the open file. [clinic start generated code]*/
static PyObject * _pickle_Pickler_dump_impl(PicklerObject *self, PyObject *obj, int num) /*[clinic end generated code: output=e80bca9c5c5a35a2 input=c6c713f75bc38e80]*/ { ...code block }
# @Time : 2021/12/26 22:43 # @Author : CharlieZhao # @File : test_multiprocessing.py # @Software: PyCharm # @Note : This module is used to test performance of multiprocessing
""" To avoid performance deficiency caused by GIL, multiprocessing is a better way to perform concurrent tasks than threading. This module is used to test performance between multiprocessing and threading. """ from multiprocessing import Process from threading import Thread import time def_print_number(info): res = 0 for i inrange(100_000_000): res = res + i print(info + " task over, result = {}".format(res)) defshow_execution_time(start_time, end_time): print("The execution time is {} s".format(end_time - start_time)) defexecute_multiprocessing_task(): """ log the execution time of multiprocessing task. :return: void """ print(" multiprocessing task start ") p1 = Process(target=_print_number, args=("Process 1",)) p2 = Process(target=_print_number, args=("Process 2",)) start = time.time() p1.start() p2.start() p1.join() p2.join() end = time.time() show_execution_time(start, end) print(" multiprocessing task end ") defexecute_threading_task(): print(" threading task start ") t1 = Thread(target=_print_number, args=("Thread 1",)) t2 = Thread(target=_print_number, args=("Thread 2",)) start = time.time() t1.start() t2.start() t1.join() t2.join() end = time.time() show_execution_time(start, end) print(" threading task end ") if __name__ == "__main__": execute_multiprocessing_task() execute_threading_task() pass """ result: multiprocessing task start Process 2 task over, result = 4999999950000000 Process 1 task over, result = 4999999950000000 The execution time is 10.988635778427124 s multiprocessing task end threading task start Thread 1 task over, result = 4999999950000000 Thread 2 task over, result = 4999999950000000 The execution time is 19.204389572143555 s threading task end 可以很直观的看到在执行两个CPU密集型的独立任务时,使用多进程相较于使用多线程效率快了一倍以上。 当然,Python多线程也不是一无是处,在执行IO密集型任务时,单单使用多进程就不太适合了。 使用多进程+多线程的模式可以绕过阻塞线程,同时相较于单进程+多线程一定程度上减少了CPU线程切换的性能损失。 """
defshow_execution_time(start_time, end_time): print("The execution time is {} s".format(end_time - start_time))
asyncdef_async_print_number(info): res = 0 for i inrange(100_000_000): res = res + i # 增加一条线程打印语句观测调用过程 print(info, " res={} in {}".format(res, threading.currentThread())) await asyncio.sleep(1) # 1s sleep 模拟IO等待,在等待时自动切换任务 print(info + " task over, result = {}".format(res))
start = time.time() loop.run_until_complete(asyncio.wait(tasks)) end = time.time()
show_execution_time(start, end) print(" async task end ")
if __name__ == "__main__": execute_async_task()
""" result: 可以看到两个任务1s为周期交替执行(实质是一个任务进入IO阻塞后,通过我们的协程调度逻辑, 在Event_loop中切换至另一个可用任务),且两个任务都在主线程中执行没有线程的切换。 async task start async task 2: res=0 in <_MainThread(MainThread, started 21168)> async task 1: res=0 in <_MainThread(MainThread, started 21168)> async task 2: res=1 in <_MainThread(MainThread, started 21168)> async task 1: res=1 in <_MainThread(MainThread, started 21168)> async task 2: res=3 in <_MainThread(MainThread, started 21168)> async task 1: res=3 in <_MainThread(MainThread, started 21168)> async task 2: res=6 in <_MainThread(MainThread, started 21168)> async task 1: res=6 in <_MainThread(MainThread, started 21168)> async task 2: res=10 in <_MainThread(MainThread, started 21168)> async task 1: res=10 in <_MainThread(MainThread, started 21168)> async task 2: res=15 in <_MainThread(MainThread, started 21168)> async task 1: res=15 in <_MainThread(MainThread, started 21168)> """